# coding=utf-8
########################## Author PiJey77@mail.com + marvin.westmaas@gmail.com
# todo From +- 900 code warnings on inspection of code down to 115 of which 58 are down to unresolved imports
# but still need to change the 32 Too broad exception clauses, and consider more error handling, I've made todo tags ;)
import BigWorld
import cPickle
import GUI
import json
import os
import csv
import codecs
import ResMgr
import math
import re
import game
import Keys
import string
import constants
import datetime
import time
import nations
from items import vehicles as vehicles_wg
from copy import copy, Error
from CurrentVehicle import g_currentVehicle
from constants import ITEM_DEFS_PATH
from messenger.m_constants import BATTLE_CHANNEL
from ChatManager import chatManager
from gui.WindowsManager import g_windowsManager
from Avatar import PlayerAvatar
from ClientArena import ClientArena
from gui import g_guiResetters
from collections import defaultdict
from gui.Scaleform.Battle import Battle, VehicleMarkersManager
from gui.BattleContext import g_battleContext
from VehicleEffects import DamageFromShotDecoder
from messenger import MessengerEntry
from items import _xml, vehicles
from Vehicle import Vehicle
from debug_utils import *
# added imports
import logger as logger
from utils import XvmScale
from utils import MultiHitLogUtils

ATTACK_REASONS = [
    'Shot',
    'Fire',
    'Ram',
    'Fall',
    'Expl',
    'Drown']
HIT_EFFECT = [
    'RICOCHET',
    'ARMOR_NOT_PIERCED',
    'ARMOR_PIERCED_NO_DAMAGE',
    'ARMOR_PIERCED',
    'CRITICAL_HIT',
    'MAX_CODE']
LOG_LEVEL = [
    'DEBUG',
    'INFO',
    'WARNING',
    'ERROR']


# noinspection PyArgumentEqualDefault
class MultiHitLog(object):
    configuration = defaultdict(dict)
    config_key = defaultdict(dict)
    window_key_list = defaultdict(dict)
    configuration_copy = defaultdict(dict)
    font = defaultdict(dict)
    windows = None
    windows_key = defaultdict(windows)
    my_config_file = ''
    my_config_ok = True
    my_cvs_ok = True
    visible_flag = True

    my_tank_exp_dmg_array = defaultdict(dict)
    tank_list_ally = defaultdict(dict)
    tank_list_enemy = defaultdict(dict)
    enemy_tank_list_sorted = defaultdict(dict)
    tank_list_descr = defaultdict(dict)
    targeted_tank_descr = defaultdict(dict)

    window_labels_key = defaultdict(dict)
    line_types_original = defaultdict(dict)
    line_types_key = defaultdict(dict)

    colors = defaultdict(dict)
    hp_left = defaultdict(dict)
    damage_log = defaultdict(dict)
    hitlog_list = defaultdict(dict)
    damagelog_list = defaultdict(dict)

    tank_counter_ally = 1
    tank_counter_enemy = 1
    hitlog_counter = 0
    hits_counter = 0
    damagelog_counter = 0
    dmg_line_counter = 0
    type_descriptor = 0
    floating_counter = 0
    total_damage = 0
    my_last_time = 0
    my_last_time2 = 0
    my_ip_timer = 0
    critical = 0

    hitlog_time = 1
    hitlog_switch = False
    damagelog_time = 1
    damagelog_switch = False
    infopanel_time = 1
    infopanel_switch = False
    is_new_damage = False

    my_hits = 0
    exp_damage = 0
    wn8 = 0
    efficiency = 0
    xwn8 = 0
    xeff = 0
    hit_type = 0
    error_message = 'Error'
    avg_damage = 0
    curr_damage = 0
    frags = 0
    last_damage = 0
    last_attacker = 0
    is_it_last = 0
    first_target = False
    penetrations = 0
    bounces = 0
    ally = 0
    hitlog_position = 0
    timer = {}
    total_damage_received = 0
    total_labels = 0
    line_multiplier = 1.4
    my_xvm_scale = XvmScale()

    def __init__(self):
        logger.info('MultiHitLog main module loading')
        # todo Add a 'default' configuration hard coded into a separate class for if load_configuration() fails??

        if not self.load_configuration():
            pass

    def load_configuration(self):
        logger.info('Loading configuration data')
        # reset to default values
        self.my_config_ok = False
        self.my_cvs_ok = False

        res = ResMgr.openSection('../paths.xml')
        sb = res['Paths']

        # todo check if this works as expected
        mod_folder = ''
        for path_value in sb:
            if 'res_mods' in path_value:
                mod_folder = path_value
                break

        # todo Add checking for file existence

        xml_file = ResMgr.openSection('scripts/client/mods/MultiHitLog/Config_File_Chooser.xml')
        self.my_config_file = xml_file.readString('ConfigFileName')

        print '                                             MultiHitLog v.1.5 by PiJey77 and mtm78'
        print '                                             MultiHitLog: Config file used:' + self.my_config_file

        logger.info('Config file :- ' + self.my_config_file)
        path = os.path.join(mod_folder, 'scripts/client/mods/MultiHitLog/Configuration')
        if os.path.isdir(path):
            conf_file = os.path.join(path, self.my_config_file)
            if os.path.isfile(conf_file):
                try:
                    # todo test
                    j_file = open(conf_file)
                    j_data = j_file.readall()
                    j_file.close()
                    self.configuration = json.load(j_data)
                    self.configuration_copy = json.load(j_data)
                    self.my_config_ok = True
                    logger.info('Configuration loaded successfully')
                except ValueError as v_error:
                    logger.warn('MultiHitLog: error in json file')
                    logger.err(v_error.message)
            else:
                logger.warn('Configuration file not found')
        else:
            logger.warn('Failed to resolve configuration path')

        path = os.path.join(mod_folder, 'scripts/client/mods/MultiHitLog/data')
        if os.path.isdir(path):
            expected_values_path = os.path.join(path, 'TankData.csv')
            if os.path.isfile(expected_values_path):
                try:
                    self.my_tank_exp_dmg_array = list(csv.reader(codecs.open(expected_values_path, encoding='cp1250')))
                    self.my_cvs_ok = True
                    logger.info('MultiHitLog: TankData.cvs loaded successfully')
                except ValueError as v_error:
                    logger.warn('MultiHitLog: error loading TankData.csv')
                    logger.err(v_error.message)
            else:
                logger.warn('TankData.csv not found', 'path :- ' + path)
        else:
            logger.warn('Failed to resolve data path', 'path :- ' + path)

        self.my_last_time = time.time()
        self.my_last_time2 = time.time()
        self.my_ip_timer = time.time()

        return self.my_cvs_ok and self.my_config_ok

    def reset_data(self):
        logger.info('MultiHitLog: reloading configuration')
        self.load_configuration()

        self.visible_flag = True
        self.tank_list_ally = defaultdict(dict)
        self.tank_list_enemy = defaultdict(dict)
        self.enemy_tank_list_sorted = defaultdict(dict)
        self.hitlog_list = defaultdict(dict)
        self.damagelog_list = defaultdict(dict)
        self.tank_counter_ally = 1
        self.tank_counter_enemy = 1
        self.total_damage = 0
        self.my_last_time = 0
        self.is_new_damage = False
        self.floating_counter = 0
        self.last_damage = 0
        self.my_hits = 0
        self.first_target = False
        self.exp_damage = 0
        self.wn8 = 0
        self.efficiency = 0
        self.xwn8 = 0
        self.xeff = 0
        self.hitlog_counter = 0
        self.hits_counter = 0
        self.error_message = 'Error'
        self.avg_damage = 0
        self.curr_damage = 0
        self.frags = 0
        self.last_attacker = 0
        self.hit_type = 0
        self.penetrations = 0
        self.bounces = 0
        self.ally = 0
        self.dmg_line_counter = 0
        self.hitlog_position = 0
        self.timer = {}
        self.total_damage_received = 0
        self.is_it_last = 0
        self.damagelog_counter = 0

    def on_change_screen_resolution(self):
        for z in xrange(0, len(self.window_key_list)):
            sr = GUI.screenResolution()
            w = self.check_width(z)
            h = self.check_height(z)
            y = self.window_key_list[z]['y']
            x = self.window_key_list[z]['x']
            if self.window_key_list[z]['xAlign'] == 'Center':
                x += (sr[0] / 2) - (w / 2)
            else:
                if x < 0:
                    x = sr[0] + x - w
            if self.window_key_list[z]['yAlign'] == 'Center':
                y += (sr[1] / 2) - (h / 4)
            else:
                if y < 0:
                    y = sr[1] + y - h
            self.windows_key[z].position = (x, y, 1)

    def insert_label(self, item, x, y, size, window):
        item.font = self.font[size]['font']
        window.addChild(item)
        item.width_mode = item.height_mode = item.vertical_position_mode = item.horizontal_position_mode = 'PIXEL'
        item.horizontal_anchor = 'LEFT'
        item.vertical_anchor = 'TOP'
        item.colour = (200, 200, 200, 255)
        item.multiple_lines = True
        item.visible = True
        item.position = (x, y, 1)

    def load_config_data(self):
        self.window_key_list = self.configuration.get('WindowKeyList')

        for z in xrange(0, len(self.window_key_list)):
            self.config_key[z] = self.configuration.get(self.window_key_list[z]['ConfigName'])

        self.colors = self.configuration.get('Colors')
        self.font = self.configuration.get('Fonts')

        for z in xrange(0, 101):
            line_type = 'Type' + str(z)
            self.line_types_original[z] = self.configuration.get(line_type)

        for z in xrange(0, len(self.window_key_list)):
            for z1 in xrange(0, len(self.config_key[z])):
                line_nr = self.check_line(self.config_key[z][z1]['LineType'])
                self.line_types_key[z][z1] = self.configuration_copy.get(self.config_key[z][z1]['LineType'])
                for z2 in xrange(0, len(self.line_types_original[line_nr])):
                    self.line_types_key[z][z1][z2]['text'] = ''
                    self.line_types_key[z][z1][z2]['color'] = MultiHitLogUtils.hextorgba('#000000')
                    self.total_labels += 1

    def check_height(self, z):
        return len(self.config_key[z]) * self.font[0]['height'] * self.line_multiplier

    def check_width(self, z):
        width_max = 0
        if self.window_key_list[z]['width'] == 0:
            for x in xrange(0, len(self.config_key[z])):
                width = 0
                if self.config_key[z][x]['LineType'] != 'Type1' and self.config_key[z][x]['LineType'] != 'Type0':
                    line_type = self.configuration.get(self.config_key[z][x]['LineType'])
                    for y in xrange(0, len(line_type)):
                        if line_type[y]['width'] != 'Center':
                            width += (line_type[y]['width'] * self.font[line_type[y]['size']]['width'])
                    if width_max < width:
                        width_max = width
            return width_max
        if self.window_key_list[z]['width'] != 0:
            return self.window_key_list[z]['width']

    def set_background(self, level, own_file):
        background = ''
        res_path = 'scripts/client/mods/MultiHitLog/Resources'
        if level == -1:
            background = os.path.join(res_path, own_file)
        if level == 0:
            background = ''
        elif level == 1:
            background = os.path.join(res_path, 'BackGround1.dds')
        elif level == 2:
            background = os.path.join(res_path, 'BackGround2.dds')
        elif level == 3:
            background = os.path.join(res_path, 'BackGround3.dds')
        elif level == 4:
            background = os.path.join(res_path, 'BackGround4.dds')
        elif level == 5:
            background = os.path.join(res_path, 'BackGround5.dds')
        elif level == 6:
            background = os.path.join(res_path, 'BackGround6.dds')
        elif level == 7:
            background = os.path.join(res_path, 'BackGround7.dds')
        elif level == 8:
            background = os.path.join(res_path, 'BackGround8.dds')
        elif level == 9:
            background = os.path.join(res_path, 'BackGround9.dds')
        elif level == 10:
            background = os.path.join(res_path, 'BackGround10.dds')
        return background

    # noinspection PyPep8Naming
    def create_windows(self):
        # note Not fixing pep8 violations for GUI.Window() descendants, add them to ignore!
        if self.my_config_ok is not True:
            print 'MultiHitLog error in json file.'
            return
        self.load_config_data()
        g_guiResetters.add(self.on_change_screen_resolution)
        for z in xrange(0, len(self.window_key_list)):
            background = self.set_background(self.window_key_list[z]['backgroundLevel'],
                                             self.window_key_list[z]['backgroundFile'])
            self.windows_key[z] = GUI.Window(background)
            self.windows_key[z].colour = (255, 255, 255, 255)
            self.windows_key[z].materialFX = "BLEND"
            self.windows_key[z].verticalAnchor = "TOP"
            self.windows_key[z].horizontalAnchor = "LEFT"
            self.windows_key[z].verticalPositionMode = self.windows_key[z].heightMode = self.windows_key[
                z].widthMode = self.windows_key[z].horizontalPositionMode = 'PIXEL'
            self.windows_key[z].width = self.check_width(z)
            self.windows_key[z].height = self.check_height(z)
            GUI.addRoot(self.windows_key[z])
        self.on_change_screen_resolution()

    def create_labels(self):
        if self.my_config_ok is not True:
            print 'MultiHitLog error in json file.'
            return
        for z in xrange(0, len(self.window_key_list)):
            y = self.window_key_list[z]['offsetY']
            for z1 in xrange(0, len(self.config_key[z])):
                x = self.window_key_list[z]['offsetX']
                # todo check if this is the error you made with y-offset not working?
                # y = z1 * self.font[0]['height'] * self.line_multiplier
                y += z1 * self.font[0]['height'] * self.line_multiplier
                line_nr = self.check_line(self.config_key[z][z1]['LineType'])
                for z2 in xrange(0, len(self.line_types_original[line_nr])):
                    un_txt_id = '1' + str(z) + str(z1) + str(z2)
                    unique_id = int(un_txt_id)
                    font_size = self.line_types_original[line_nr][z2]['size']
                    if self.line_types_original[line_nr][z2]['width'] == 'Center':
                        x = (self.check_width(z) / 2) - ((len(self.line_types_original[line_nr][z2]['text']) *
                                                          self.font[font_size]['width']) / 2)
                    self.window_labels_key[unique_id] = GUI.Text('')
                    self.insert_label(self.window_labels_key[unique_id], x, y, font_size, self.windows_key[z])
                    if self.line_types_original[line_nr][z2]['width'] != 'Center':
                        key_width = self.line_types_original[line_nr][z2]['width']
                        x += key_width * (self.font[font_size]['width'])

    def key_pressed(self, text):
        if self.damagelog_switch is True:
            self.infopanel_switch = False
            self.infopanel_time = 0
            self.hitlog_switch = False
            self.hitlog_time = 0

        elif self.infopanel_switch is True:
            self.hitlog_switch = False
            self.hitlog_time = 0
            self.damagelog_switch = False
            self.damagelog_time = 0

        elif self.hitlog_switch is True:
            self.damagelog_switch = False
            self.damagelog_time = 0
            self.infopanel_switch = False
            self.infopanel_time = 0

        for z in xrange(0, len(self.window_key_list)):
            if self.window_key_list[z]['Key'] == "HitLog" and self.hitlog_switch is True:
                self.hitlog_time = time.time()
                self.hitlog_switch = False
                try:
                    self.windows_key[z].visible = self.visible_flag
                finally:
                    pass

            if self.window_key_list[z]['Key'] == "HitLog" and self.hitlog_switch is False:
                if (time.time() - self.window_key_list[z]['time']) > self.hitlog_time or self.hitlog_time == 0:
                    try:
                        self.windows_key[z].visible = False
                    finally:
                        pass
                else:
                    for z2 in xrange(0, len(self.window_key_list)):
                        if z != z2:
                            if self.window_key_list[z2]['xAlign'] == self.window_key_list[z]['xAlign']:
                                if self.window_key_list[z2]['yAlign'] == self.window_key_list[z]['yAlign']:
                                    if self.window_key_list[z2]['x'] == self.window_key_list[z]['x']:
                                        if self.window_key_list[z2]['y'] == self.window_key_list[z]['y']:
                                            try:
                                                self.windows_key[z2].visible = False
                                            except:
                                                pass

            if self.window_key_list[z]['Key'] == "DamageLog" and self.damagelog_switch is True:
                self.damagelog_time = time.time()
                self.damagelog_switch = False
                try:
                    self.windows_key[z].visible = self.visible_flag
                finally:
                    pass

            if self.window_key_list[z]['Key'] == "DamageLog" and self.damagelog_switch is False:
                if (time.time() - self.window_key_list[z]['time']) > self.damagelog_time or self.damagelog_time == 0:
                    try:
                        self.windows_key[z].visible = False
                    finally:
                        pass
                else:
                    for z2 in xrange(0, len(self.window_key_list)):
                        if z != z2:
                            if self.window_key_list[z2]['xAlign'] == self.window_key_list[z]['xAlign']:
                                if self.window_key_list[z2]['yAlign'] == self.window_key_list[z]['yAlign']:
                                    if self.window_key_list[z2]['x'] == self.window_key_list[z]['x']:
                                        if self.window_key_list[z2]['y'] == self.window_key_list[z]['y']:
                                            try:
                                                self.windows_key[z2].visible = False
                                            finally:
                                                pass

            if self.window_key_list[z]['Key'] == "InfoPanel" and self.infopanel_switch is True:
                self.infopanel_time = time.time()
                self.infopanel_switch = False
                try:
                    self.windows_key[z].visible = self.visible_flag
                except:
                    pass

            if self.window_key_list[z]['Key'] == "InfoPanel" and self.infopanel_switch is False:
                if (time.time() - self.window_key_list[z]['time']) > self.infopanel_time or self.infopanel_time == 0:
                    try:
                        self.windows_key[z].visible = False
                    finally:
                        pass
                else:
                    for z2 in xrange(0, len(self.window_key_list)):
                        if z != z2:
                            if self.window_key_list[z2]['xAlign'] == self.window_key_list[z]['xAlign']:
                                if self.window_key_list[z2]['yAlign'] == self.window_key_list[z]['yAlign']:
                                    if self.window_key_list[z2]['x'] == self.window_key_list[z]['x']:
                                        if self.window_key_list[z2]['y'] == self.window_key_list[z]['y']:
                                            try:
                                                self.windows_key[z2].visible = False
                                            finally:
                                                pass

        for z in xrange(0, len(self.window_key_list)):
            if self.window_key_list[z]['Key'] != 'HitLog' and self.window_key_list[z]['Key'] != 'DamageLog' and \
                            self.window_key_list[z]['Key'] != 'InfoPanel':
                try:
                    self.windows_key[z].visible = False
                finally:
                    pass

        found = False
        for z in xrange(0, len(self.window_key_list)):
            if self.window_key_list[z]['Key'] == text:
                found = True
                try:
                    self.windows_key[z].visible = self.visible_flag
                finally:
                    pass

                for z2 in xrange(0, len(self.window_key_list)):
                    if z != z2:
                        if self.window_key_list[z2]['xAlign'] == self.window_key_list[z]['xAlign']:
                            if self.window_key_list[z2]['yAlign'] == self.window_key_list[z]['yAlign']:
                                if self.window_key_list[z2]['x'] == self.window_key_list[z]['x']:
                                    if self.window_key_list[z2]['y'] == self.window_key_list[z]['y']:
                                        try:
                                            self.windows_key[z2].visible = False
                                        except:
                                            pass
        for z in xrange(0, len(self.window_key_list)):
            if found is False and self.window_key_list[z]['Key'] == 'NONE':
                try:
                    self.windows_key[z].visible = self.visible_flag
                finally:
                    pass
            if self.window_key_list[z]['Key'] == 'ALWAYS':
                try:
                    self.windows_key[z].visible = self.visible_flag
                finally:
                    pass
        return

    def pass_type_descriptor(self, type_descriptor):
        self.type_descriptor = type_descriptor

    def set_visible(self, flag):
        self.visible_flag = flag
        for z in xrange(0, len(self.window_key_list)):
            self.windows_key[z].visible = flag

    def delete_window(self):
        for z in xrange(0, len(self.window_key_list)):
            GUI.delRoot(self.windows_key[z])
            self.windows_key[z] = None

    def check_battle_type(self):
        player = BigWorld.player()
        battle_type = player.arena.guiType
        # you have an else statement meaning you don't need to declare the variable before the if branching
        # battle_type_name = ''
        if battle_type == constants.ARENA_GUI_TYPE.RANDOM:
            battle_type_name = 'Random'
        elif battle_type == constants.ARENA_GUI_TYPE.TRAINING:
            battle_type_name = 'Training'
        elif battle_type == constants.ARENA_GUI_TYPE.COMPANY:
            battle_type_name = 'Company'
        elif battle_type == constants.ARENA_GUI_TYPE.CYBERSPORT:
            battle_type_name = 'CyberSport'
        else:
            battle_type_name = 'ClanWar'
        return battle_type_name

    def calculate_efficiencies(self, x_damage, exp_damage, r_spot, r_frag, frags, r_def, r_win, r_tier):
        r_damage = float(x_damage) / float(exp_damage)
        r_spot = 0 / float(r_spot)
        r_frag = float(frags) / float(r_frag)
        r_def = 0 / float(r_def)
        r_win = 0 / float(r_win)
        r_win_c = max(0, int(r_win) - 0.71 / (1 - 0.71))

        r_damage_c = max(0, (r_damage - 0.22) / (1 - 0.22))
        r_frags_c = max(0, min(r_damage_c + 0.2, (r_frag - 0.12) / (1 - 0.12)))
        r_spot_c = max(0, min(r_damage_c + 0.1, (r_spot - 0.38) / (1 - 0.38)))
        r_def_c = max(0, min(r_damage_c + 0.1, (r_def - 0.10) / (1 - 0.10)))
        wn8 = 980 * r_damage_c + 210 * r_damage_c * r_frags_c + 155 * r_frags_c * r_spot_c + 75 * r_def_c * r_frags_c \
              + 145 * min(1.8, r_win_c)

        avg_damage = float(x_damage)
        avg_frags = float(frags)
        avg_spot = float(r_spot)
        avg_def = float(r_def)
        avg_cap = float(0)
        avg_tier = float(r_tier)
        eff = max(0, int(
            avg_damage * (10 / (avg_tier + 2)) * (0.23 + 2 * avg_tier / 100) + avg_frags * 250 + avg_spot * 150 +
            math.log(avg_cap + 1, 1.732) * 150 + avg_def * 150))

        xwn8, xeff = self.my_xvm_scale.convert_to_xwnscale(wn8, eff)

        return int(wn8), int(eff), int(xwn8), int(xeff)

    # todo @PiJey77 check necessity for unused variables
    def check_macros(self, text, battle_id, hl_pos, attacker_reason_id, attacker_id=0, damage=0, effects_index=0,
                     place='', width=0, hit_nr=-1):
        try:
            player = BigWorld.player()
            # current = player.arena.vehicles.get(battle_id)
            attacker = player.arena.vehicles.get(attacker_id)
            # current_vehicle_id = player.playerVehicleID
        except ValueError:
            # todo add error checking here
            pass
        finally:
            pass

        if attacker is None:
            logger.warn('MultiHitLog - check_macros :- attacker is None')
            # todo how about not continuing function when player is None?
            # return

        attacker_ammo = 'credit'
        attacker_shell_type = ''

        try:
            for shell in attacker['vehicleType'].gun['shots']:
                if effects_index == shell['shell']['effectsIndex']:
                    price = self.get_shell_info(shell['shell']['id'][0], shell['shell']['id'][1])
                    if price[1] != 0:
                        attacker_ammo = 'gold'
                    else:
                        attacker_ammo = 'credit'

                    if shell['shell']['kind'] == 'ARMOR_PIERCING':
                        attacker_shell_type = self.configuration.get('AP_Shell')

                    if shell['shell']['kind'] == 'ARMOR_PIERCING_CR':
                        attacker_shell_type = self.configuration.get('APCR_Shell')

                    if shell['shell']['kind'] == 'ARMOR_PIERCING' and attacker_ammo == 'gold':
                        attacker_shell_type = self.configuration.get('APCR_G_Shell')

                    if shell['shell']['kind'] == 'HIGH_EXPLOSIVE' and attacker_ammo == 'credit':
                        attacker_shell_type = self.configuration.get('HE_Shell')

                    if shell['shell']['kind'] == 'HIGH_EXPLOSIVE' and attacker_ammo == 'gold':
                        attacker_shell_type = self.configuration.get('HESH_G_Shell')

                    if shell['shell']['kind'] == 'HOLLOW_CHARGE':
                        attacker_shell_type = self.configuration.get('HEAT_G_Shell')
                    break
        finally:
            pass

        if '{{DL_HitNr}}' in text:
            text_x = str(hit_nr).zfill(2)
            text = text.replace('{{DL_HitNr}}', text_x)

        if '{{DL_AttackerDamage}}' in text:
            text_x = str(damage)
            text = text.replace('{{DL_AttackerDamage}}', text_x)

        if '{{DL_AttackerAmmo}}' in text:
            text_x = str(attacker_shell_type)
            text = text.replace('{{DL_AttackerAmmo}}', text_x)

        if '{{DL_AttackType}}' in text:
            text_x = str(ATTACK_REASONS[attacker_reason_id])
            text = text.replace('{{DL_AttackType}}', text_x)

        if '{{DL_AttackerTank}}' in text:
            text_x = str(unicode(attacker['vehicleType'].type.shortUserString))
            if width > 0:
                text_x = text_x[0:width]
                text = text.replace('{{DL_AttackerTank}}', text_x)

        if '{{DL_AttackerName}}' in text:
            text_x = str(attacker['name'])
            if width > 0:
                text_x = text_x[0:width]
            text = text.replace('{{DL_AttackerName}}', text_x)

        if '{{DL_AttackerPlace}}' in text:
            text_x = str(place)
            text = text.replace('{{DL_AttackerPlace}}', text_x)

        if '{{DL_AttackerReload}}' in text:
            # todo @PiJey77 review code changes..
            # you can't see from a tank if it has a rammer and ventilation, so don't use it ;)
            # I've also shortened the code a tiny bit
            if self.configuration['OptionalEquipment']['Rammer'] == 'Ventilation':
                loader_skill = 132.0
            else:
                loader_skill = 126.5
            if self.configuration['OptionalEquipment']['Gun-rammer'] == 'True':
                other_bonus = 0.9
            else:
                other_bonus = 1
            reload_time = attacker['vehicleType'].gun['reloadTime']
            reload_time = reload_time * 0.875 / (0.00375 * loader_skill + 0.5) * other_bonus
            reload_time_text = "{:.2f}".format(reload_time)
            reload_time_text += 's'
            text = text.replace('{{DL_AttackerReload}}', reload_time_text)

        if '{{HL_DMG}}' in text:
            text = text.replace('{{HL_DMG}}', str(self.total_damage))
        if '{{HL_WN8}}' in text:
            text = text.replace('{{HL_WN8}}', str(int(self.wn8)))
        if '{{HL_EFF}}' in text:
            text = text.replace('{{HL_EFF}}', str(int(self.efficiency)))
        if '{{HL_XWN8}}' in text:
            text = text.replace('{{HL_XWN8}}', str(int(self.xwn8)))
        if '{{HL_XEFF}}' in text:
            text = text.replace('{{HL_XEFF}}', str(int(self.xeff)))
        if '{{HL_Diff}}' in text:
            text = text.replace('{{HL_Diff}}', str(int(self.curr_damage)))
        if '{{HL_Shots}}' in text:
            text = text.replace('{{HL_Shots}}', str(int(self.my_hits)))
        if '{{HL_AvgDMG}}' in text:
            text = text.replace('{{HL_AvgDMG}}', str(int(self.avg_damage)))
        if '{{HL_LastDMG}}' in text:
            text = text.replace('{{HL_LastDMG}}', str(int(self.last_damage)))
        if '{{DL_TotalPen}}' in text:
            text = text.replace('{{DL_TotalPen}}', str(int(self.penetrations)))
        if '{{DL_TotalBounce}}' in text:
            text = text.replace('{{DL_TotalBounce}}', str(int(self.bounces)))
        if '{{DL_TotalAlly}}' in text:
            text = text.replace('{{DL_TotalAlly}}', str(int(self.ally)))
        if '{{DL_ReceivedHits}}' in text:
            received_hits = int(self.penetrations) + int(self.bounces) + int(self.ally)
            text = text.replace('{{DL_ReceivedHits}}', str(received_hits))
        if '{{DL_TotalReceived}}' in text:
            text = text.replace('{{DL_TotalReceived}}', str(self.total_damage_received))

        if '{{HL_Hits}}' in text and hl_pos >= 0:
            text = text.replace('{{HL_Hits}}', str(int(self.hitlog_list[hl_pos]['Hits'])))
        elif '{{HL_Hits}}' in text and hl_pos < 0:
            text = ''

        if '{{HL_TotalDamage}}' in text and hl_pos >= 0:
            text = text.replace('{{HL_TotalDamage}}', str(int(self.hitlog_list[hl_pos]['TotalDamage'])))
        elif '{{HL_TotalDamage}}' in text and hl_pos < 0:
            text = ''

        if '{{HL_LastDamage}}' in text and hl_pos >= 0:
            text = text.replace('{{HL_LastDamage}}', str(int(self.hitlog_list[hl_pos]['LastDamage'])))
        elif '{{HL_LastDamage}}' in text and hl_pos < 0:
            text = ''

        if '{{HL_Tank}}' in text and hl_pos >= 0:
            text_x = str(self.hitlog_list[hl_pos]['Tank'])
            if width > 0:
                text_x = text_x[0:width]
            text = text.replace('{{HL_Tank}}', text_x)
        elif '{{HL_Tank}}' in text and hl_pos < 0:
            text = ''

        if '{{HL_Name}}' in text and hl_pos >= 0:
            text_x = str(self.hitlog_list[hl_pos]['Name'])
            if width > 0:
                text_x = text_x[0:width]
            text = text.replace('{{HL_Name}}', text_x)
        elif '{{HL_Name}}' in text and hl_pos < 0:
            text = ''

        if '{{HL_Killed}}' in text and hl_pos >= 0:
            if self.hitlog_list[hl_pos]['Killed'] == 'False':
                text = text.replace('{{HL_Killed}}', '')
            if self.hitlog_list[hl_pos]['Killed'] == 'True':
                text = text.replace('{{HL_Killed}}', self.configuration.get('HL_Killed_Text'))
        elif '{{HL_Killed}}' in text and hl_pos < 0:
            text = ''

        if '{{HL_Ally}}' in text and hl_pos >= 0:
            if self.hitlog_list[hl_pos]['Ally'] == 'False':
                text = text.replace('{{HL_Ally}}', '')
            if self.hitlog_list[hl_pos]['Ally'] == 'True':
                text = text.replace('{{HL_Ally}}', self.configuration.get('HL_Ally_Text'))
        elif '{{HL_Ally}}' in text and hl_pos < 0:
            text = ''
        # todo fix to broad exception handling, replace with except ValueError: ??
        if '{{HL_AttackType}}' in text and hl_pos >= 0:
            text = text.replace('{{HL_AttackType}}', str(ATTACK_REASONS[self.hitlog_list[hl_pos]['Attack']]))
        elif '{{HL_AttackType}}' in text and hl_pos < 0:
            text = ''

        if '{{DL_AttackType}}' in text:
            try:
                text = text.replace('{{DL_AttackType}}', str(ATTACK_REASONS[attacker_reason_id]))
            except:
                text = ''
        if '{{HP_EnemyTank}}' in text:
            try:
                text = text.replace('{{HP_EnemyTank}}', str(self.enemy_tank_list_sorted[hl_pos]['tankName']))
            except:
                text = ''
        if '{{HP_EnemyName}}' in text:
            try:
                text = text.replace('{{HP_EnemyName}}', str(self.enemy_tank_list_sorted[hl_pos]['playerName']))
            except:
                text = ''
        if '{{HP}}' in text:
            try:
                text = text.replace('{{HP}}', str(int(self.enemy_tank_list_sorted[hl_pos]['maxHealth'])))
            except:
                text = ''
        if '{{HP_Left}}' in text:
            try:
                text = text.replace('{{HP_Left}}', str(int(self.enemy_tank_list_sorted[hl_pos]['currentHealth'])))
            except:
                text = ''

        if '{{IP_Tank}}' in text:
            text_x = str(self.targeted_tank_descr['TankName'])
            if width > 0:
                text_x = text_x[0:width]
            try:
                text = text.replace('{{IP_Tank}}', text_x)
            except:
                pass
        if '{{IP_Reload}}' in text:
            reload_time = float(self.targeted_tank_descr.get('ReloadTime') or 0)
            reload_time_text = "{:.2f}".format(reload_time)
            try:
                text = text.replace('{{IP_Reload}}', reload_time_text)
            except:
                pass
        if '{{IP_Gun}}' in text:
            text_x = str(self.targeted_tank_descr['gunName'])
            if width > 0:
                text_x = text_x[0:width]
            try:
                text = text.replace('{{IP_Gun}}', text_x)
            except:
                pass
        if '{{IP_ViewRange}}' in text:
            try:
                text = text.replace('{{IP_ViewRange}}', str(self.targeted_tank_descr['ViewRange']))
            except:
                pass

        if '{{IP_TargetWeight}}' in text:
            t_weight = self.targeted_tank_descr.get('vWeight')
            try:
                text = text.replace('{{IP_TargetWeight}}', str(t_weight))
            except:
                pass

        if '{{IP_MyWeight}}' in text:
            o_weight = self.targeted_tank_descr.get('pWeight')
            try:
                text = text.replace('{{IP_MyWeight}}', str(o_weight))
            except:
                pass

        if '{{IP_WeightDiff}}' in text:
            o_weight = self.targeted_tank_descr.get('pWeight')
            t_weight = self.targeted_tank_descr.get('vWeight')
            weight = int(o_weight or 0) - int(t_weight or 0)
            try:
                text = text.replace('{{IP_WeightDiff}}', str(weight))
            except:
                pass

        if '{{IP_AmmoType1}}' in text:
            try:
                text = text.replace('{{IP_AmmoType1}}', str(self.targeted_tank_descr['shellType'][0]))
            except:
                pass
        if '{{IP_AmmoType2}}' in text:
            try:
                text = text.replace('{{IP_AmmoType2}}', str(self.targeted_tank_descr['shellType'][1]))
            except:
                pass
        if '{{IP_AmmoType3}}' in text:
            try:
                text = text.replace('{{IP_AmmoType3}}', str(self.targeted_tank_descr['shellType'][2]))
            except:
                pass

        if '{{IP_AmmoPen1}}' in text:
            try:
                text = text.replace('{{IP_AmmoPen1}}', str(self.targeted_tank_descr['shellPower'][0]))
            except:
                pass
        if '{{IP_AmmoPen2}}' in text:
            try:
                text = text.replace('{{IP_AmmoPen2}}', str(self.targeted_tank_descr['shellPower'][1]))
            except:
                pass
        if '{{IP_AmmoPen3}}' in text:
            try:
                text = text.replace('{{IP_AmmoPen3}}', str(self.targeted_tank_descr['shellPower'][2]))
            except:
                pass

        if '{{IP_AmmoDamage1}}' in text:
            try:
                text = text.replace('{{IP_AmmoDamage1}}', str(self.targeted_tank_descr['shellDamage'][0]))
            except:
                pass
        if '{{IP_AmmoDamage2}}' in text:
            try:
                text = text.replace('{{IP_AmmoDamage2}}', str(self.targeted_tank_descr['shellDamage'][1]))
            except:
                pass
        if '{{IP_AmmoDamage3}}' in text:
            try:
                text = text.replace('{{IP_AmmoDamage3}}', str(self.targeted_tank_descr['shellDamage'][2]))
            except:
                pass

        if '{{IP_HullF}}' in text:
            try:
                text = text.replace('{{IP_HullF}}', str(self.targeted_tank_descr['hullArmor'][0]))
            except:
                pass
        if '{{IP_HullS}}' in text:
            try:
                text = text.replace('{{IP_HullS}}', str(self.targeted_tank_descr['hullArmor'][1]))
            except:
                pass
        if '{{IP_HullR}}' in text:
            try:
                text = text.replace('{{IP_HullR}}', str(self.targeted_tank_descr['hullArmor'][2]))
            except:
                pass

        if '{{IP_TurretF}}' in text:
            try:
                text = text.replace('{{IP_TurretF}}', str(self.targeted_tank_descr['turretArmor'][0]))
            except:
                pass
        if '{{IP_TurretS}}' in text:
            try:
                text = text.replace('{{IP_TurretS}}', str(self.targeted_tank_descr['turretArmor'][1]))
            except:
                pass
        if '{{IP_TurretR}}' in text:
            try:
                text = text.replace('{{IP_TurretR}}', str(self.targeted_tank_descr['turretArmor'][2]))
            except:
                pass

        return text, attacker_ammo

    # todo remove color_type from arguments list
    def check_color(self, c_color, color_type='', attacker_ammo='credit', attack_reason_id=0, weight='even'):
        if c_color == 'diff':
            hex_color = '#FFFFFF'
            if self.curr_damage < 0:
                hex_color = self.colors['diff']['less']['color']
            elif self.curr_damage == 0:
                hex_color = self.colors['diff']['equal']['color']
            elif self.curr_damage > 9:
                hex_color = self.colors['diff']['more']['color']

            return MultiHitLogUtils.hextorgba(hex_color)

        if c_color == 'WN8':
            hex_color = '#000000'
            for color_entry in self.colors['WN8']:
                if self.wn8 >= color_entry['value']:
                    hex_color = color_entry['color']
                else:
                    break
            return MultiHitLogUtils.hextorgba(hex_color)

        if c_color == 'EFF':
            hex_color = '#FFFFFF'
            for color_entry in self.colors['EFF']:
                if self.wn8 >= color_entry['value']:
                    hex_color = color_entry['color']
                else:
                    break
            return MultiHitLogUtils.hextorgba(hex_color)

        if c_color == 'hit':
            hex_color = '#FFFFFF'
            for color_entry in self.colors['hit']:
                if color_type == color_entry['value']:
                    hex_color = color_entry['color']
                    break
            return MultiHitLogUtils.hextorgba(hex_color)

        if c_color == 'ammo':
            hex_color = '#FFFFFF'
            for color_entry in self.colors['ammo']:
                if color_entry['value'] == attacker_ammo:
                    hex_color = color_entry['color']
                    break
            return MultiHitLogUtils.hextorgba(hex_color)

        if c_color == 'damage':
            hex_color = '#FFFFFF'
            for color_entry in self.colors['damage']:
                if color_entry['value'] == ATTACK_REASONS[attack_reason_id]:
                    hex_color = color_entry['color']
                    break
            return MultiHitLogUtils.hextorgba(hex_color)

        if c_color == 'weight':
            hex_color = '#FFFFFF'
            for color_entry in self.colors['weight']:
                if color_entry['value'] == weight:
                    hex_color = color_entry['color']
                    break
            return MultiHitLogUtils.hextorgba(hex_color)

        return MultiHitLogUtils.hextorgba(c_color)

    def get_shell_info(self, nation_id, shell_id):
        price = {}
        # is_hesh_ammo = False
        xml_path = ITEM_DEFS_PATH + 'vehicles/' + nations.NAMES[nation_id] + '/components/shells.xml'
        for name, subsection in ResMgr.openSection(xml_path).items():
            if name != 'icons':
                xml_ctx = (None, xml_path + '/' + name)
                if _xml.readInt(xml_ctx, subsection, 'id', 0, 65535) == shell_id:
                    price = _xml.readPrice(xml_ctx, subsection, 'price')
                    # todo configure access to xml file with resMgr or own Xml parser so we can read the 'name' field
                    break
        ResMgr.purge(xml_path, True)
        return price

    # todo attacker_id is not used, do we need it?
    def update_total_damage(self, battle_id, my_damage, new_health, attacker_id, attack_reason_id):
        self.update_hitlog(battle_id, my_damage, new_health, attack_reason_id)
        if BigWorld.player().arena.vehicles.get(battle_id)['team'] != BigWorld.player().team:
            self.total_damage += my_damage
            current_time = time.time() - 5
            if current_time > self.my_last_time2:
                self.my_last_time2 = time.time()
                self.is_new_damage = True
            else:
                self.is_new_damage = False
            if attack_reason_id == 0:
                self.my_hits += 1
            self.last_damage = my_damage
        self.update_efficiencies()

    # noinspection PyProtectedMember
    def update_efficiencies(self):
        if not self.my_config_ok:
            logger.warn('MultiHitLog - update_efficiencies :- error in json file!')
            print 'MultiHitLog error in json file.'

        # player = BigWorld.player()
        # own_id = BigWorld.player().playerVehicleID
        # current = player.arena.vehicles.get(own_id)
        # VehicleFullName = current['vehicleType'].type.userString

        self.frags = len(BigWorld.player()._PlayerAvatar__frags)
        self.exp_damage = 0
        self.wn8 = 0
        self.efficiency = 0
        self.xwn8 = 0
        self.error_message = 'Error'
        self.xeff = 0
        self.avg_damage = 0
        self.curr_damage = 0

        keys = len(self.my_tank_exp_dmg_array)
        for xx in xrange(1, keys):
            if self.type_descriptor != 0:
                if self.type_descriptor.type.id[0] == (int(self.my_tank_exp_dmg_array[xx][9]) >> 4 & 15) and \
                                self.type_descriptor.type.id[1] == \
                                (int(self.my_tank_exp_dmg_array[xx][9]) >> 8 & 65535):
                    self.exp_damage = self.my_tank_exp_dmg_array[xx][2]
                    r_spot = self.my_tank_exp_dmg_array[xx][3]
                    r_frag = self.my_tank_exp_dmg_array[xx][1]
                    r_def = self.my_tank_exp_dmg_array[xx][4]
                    r_win = self.my_tank_exp_dmg_array[xx][5]
                    r_tier = self.my_tank_exp_dmg_array[xx][6]
                    self.wn8, self.efficiency, self.xwn8, self.xeff = self.calculate_efficiencies(self.total_damage,
                                                                                                  self.exp_damage,
                                                                                                  r_spot, r_frag,
                                                                                                  self.frags, r_def,
                                                                                                  r_win, r_tier)
                    self.error_message = 'OK'
                    break
            else:
                self.error_message = 'NotYet'

        if self.error_message == 'Error':
            print 'MultiHitLog error: no data for current tank'

        self.curr_damage = float(self.total_damage) - float(self.exp_damage)
        if self.my_hits > 0:
            self.avg_damage = float(self.total_damage) / float(self.my_hits)
        else:
            self.avg_damage = 0
        for z in xrange(0, len(self.window_key_list)):
            for z1 in xrange(0, len(self.config_key[z])):
                line_nr = self.check_line(self.config_key[z][z1]['LineType'])
                if line_nr != 4 and line_nr != 6 and line_nr != 7:
                    for z2 in xrange(0, len(self.line_types_original[line_nr])):
                        unid_txt = '1' + str(z) + str(z1) + str(z2)
                        unid = int(unid_txt)
                        self.window_labels_key[unid].text, ammo = self.check_macros(
                            self.line_types_original[line_nr][z2]['text'], 0, -1, 0)
                        self.window_labels_key[unid].colour = self.check_color(
                            self.line_types_original[line_nr][z2]['color'], ammo)

    # noinspection PyArgumentEqualDefault
    def update_hitlog(self, battle_id=0, my_damage=0, new_health=0, attack_reason_id=0):
        self.hitlog_switch = True
        position = self.hitlog_counter
        found = False
        self.hitlog_position = 0
        if self.configuration.get('groupHitLog') == 'True':
            for z in xrange(0, position):
                if self.hitlog_list[z]['Name'] == BigWorld.player().arena.vehicles.get(battle_id)[
                    'name']:  # vehicle.shortUserName
                    self.hitlog_list[z]['Hits'] += 1
                    self.hitlog_list[z]['TotalDamage'] += my_damage
                    self.hitlog_list[z]['LastDamage'] = my_damage
                    self.hitlog_list[z]['Attack'] = attack_reason_id
                    if new_health <= 0:
                        self.hitlog_list[z]['Killed'] = 'True'
                    found = True
        if not found:
            for z in xrange(1, self.tank_counter_enemy):
                if self.tank_list_enemy[z]['playerName']:
                    if self.tank_list_enemy[z]['playerName'] == BigWorld.player().arena.vehicles.get(battle_id)['name']:
                        self.hitlog_list[position]['Hits'] = 1
                        self.hitlog_list[position]['TotalDamage'] = my_damage
                        self.hitlog_list[position]['LastDamage'] = my_damage
                        self.hitlog_list[position]['Tank'] = self.tank_list_enemy[z]['tankName']
                        self.hitlog_list[position]['Name'] = self.tank_list_enemy[z]['playerName']
                        self.hitlog_list[position]['Attack'] = attack_reason_id
                        self.hitlog_list[position]['Ally'] = 'False'
                        if new_health <= 0:
                            self.hitlog_list[position]['Killed'] = 'True'
                        else:
                            self.hitlog_list[position]['Killed'] = 'False'
                        self.hitlog_counter += 1
                        break
            for z in xrange(1, self.tank_counter_ally):
                if self.tank_list_ally[z]['playerName']:
                    if self.tank_list_ally[z]['playerName'] == BigWorld.player().arena.vehicles.get(battle_id)['name']:
                        self.hitlog_list[position]['Hits'] = 1
                        self.hitlog_list[position]['TotalDamage'] = my_damage
                        self.hitlog_list[position]['LastDamage'] = my_damage
                        self.hitlog_list[position]['Tank'] = self.tank_list_ally[z]['tankName']
                        self.hitlog_list[position]['Name'] = self.tank_list_ally[z]['playerName']
                        self.hitlog_list[position]['Attack'] = attack_reason_id
                        self.hitlog_list[position]['Ally'] = 'True'
                        self.hitlog_list[position]['Killed'] = 'False'
                        if new_health <= 0:
                            self.hitlog_list[position]['Killed'] = 'True'
                        else:
                            self.hitlog_list[position]['Killed'] = 'False'
                        self.hitlog_counter += 1
                        break
        for z in xrange(0, len(self.window_key_list)):
            hitlog_position = self.hitlog_counter
            for z1 in xrange(0, len(self.config_key[z])):
                line_nr = self.check_line(self.config_key[z][z1]['LineType'])
                if line_nr == 4:
                    hitlog_position -= 1
                    for z2 in xrange(0, len(self.line_types_original[line_nr])):
                        unid_txt = '1' + str(z) + str(z1) + str(z2)
                        unid = int(unid_txt)
                        hitlog_width = self.line_types_original[line_nr][z2]['width']
                        text = str(self.line_types_original[line_nr][z2]['text'])
                        self.window_labels_key[unid].text, ammo = self.check_macros(text, battle_id, hitlog_position,
                                                                                    attack_reason_id, 0, my_damage, 0,
                                                                                    0,
                                                                                    hitlog_width)
                        self.window_labels_key[unid].colour = self.check_color(
                            self.line_types_original[line_nr][z2]['color'],
                            '', ammo, attack_reason_id)
        self.update_efficiencies()

    # commented out not used variables
    def update_damage_log(self, battle_id, attacker_id, attack_reason_id, damage, effects_index, health, when, place):
        player = BigWorld.player()
        # current = player.arena.vehicles.get(battle_id)
        attacker = player.arena.vehicles.get(attacker_id)  # Attacker vehicle
        current_vehicle_id = player.playerVehicleID  # My vehicle
        # own_vehicle_id = BigWorld.player().playerVehicleID
        # own_vehicle = player.arena.vehicles.get(own_vehicle_id)
        change = False

        if self.is_it_last != 2 and health > 0 and self.last_attacker == attacker_id and when <= (
                    self.my_last_time + 0.2) and attacker_id != current_vehicle_id and attack_reason_id == 0:
            if self.dmg_line_counter >= 1:
                self.dmg_line_counter -= 1
            else:
                self.dmg_line_counter = 0
            if self.bounces > 0:
                self.bounces -= 1
            else:
                self.bounces = 0
            place = self.critical
        if self.is_it_last != 2 and health > 0:
            self.my_last_time = when
            self.last_attacker = attacker_id
            if battle_id == current_vehicle_id and player.team != attacker[
                'team'] and damage > 0 and self.configuration.get('ShowPen') == 'True':  # PENETRATION
                self.damagelog_switch = True
                if attack_reason_id == 0:
                    self.penetrations += 1
                self.dmg_line_counter += 1
                dng_type = 'pen'
                self.total_damage_received += damage
                self.damagelog_list[self.dmg_line_counter]['battleID'] = battle_id
                self.damagelog_list[self.dmg_line_counter]['attackReasonID'] = attack_reason_id
                self.damagelog_list[self.dmg_line_counter]['attackerID'] = attacker_id
                self.damagelog_list[self.dmg_line_counter]['Damage'] = damage
                self.damagelog_list[self.dmg_line_counter]['effectsIndex'] = effects_index
                self.damagelog_list[self.dmg_line_counter]['myHealth'] = health
                self.damagelog_list[self.dmg_line_counter]['place'] = place
                self.damagelog_list[self.dmg_line_counter]['type'] = dng_type
                self.damagelog_list[self.dmg_line_counter]['Nr'] = self.dmg_line_counter
                change = True

            elif battle_id == current_vehicle_id and player.team != attacker[
                'team'] and damage <= 0 and self.configuration.get(
                    'ShowBounce') == 'True':  # BOUNCE
                self.damagelog_switch = True
                self.bounces += 1
                self.dmg_line_counter += 1
                self.critical = place
                dng_type = 'bounce'
                self.damagelog_list[self.dmg_line_counter]['battleID'] = battle_id
                self.damagelog_list[self.dmg_line_counter]['attackReasonID'] = attack_reason_id
                self.damagelog_list[self.dmg_line_counter]['attackerID'] = attacker_id
                self.damagelog_list[self.dmg_line_counter]['Damage'] = damage
                self.damagelog_list[self.dmg_line_counter]['effectsIndex'] = effects_index
                self.damagelog_list[self.dmg_line_counter]['myHealth'] = health
                self.damagelog_list[self.dmg_line_counter]['place'] = place
                self.damagelog_list[self.dmg_line_counter]['type'] = dng_type
                self.damagelog_list[self.dmg_line_counter]['Nr'] = self.dmg_line_counter
                change = True

            elif battle_id == current_vehicle_id and player.team == attacker['team'] and self.configuration.get(
                    'ShowAlly') == 'True':  # FRIENDLY FIRE
                self.damagelog_switch = True
                if attack_reason_id == 0 and damage > 0:
                    self.ally += 1
                self.dmg_line_counter += 1
                dng_type = 'ally'
                self.damagelog_list[self.dmg_line_counter]['battleID'] = battle_id
                self.damagelog_list[self.dmg_line_counter]['attackReasonID'] = attack_reason_id
                self.damagelog_list[self.dmg_line_counter]['attackerID'] = attacker_id
                self.damagelog_list[self.dmg_line_counter]['Damage'] = damage
                self.damagelog_list[self.dmg_line_counter]['effectsIndex'] = effects_index
                self.damagelog_list[self.dmg_line_counter]['myHealth'] = health
                self.damagelog_list[self.dmg_line_counter]['place'] = place
                self.damagelog_list[self.dmg_line_counter]['type'] = dng_type
                self.damagelog_list[self.dmg_line_counter]['Nr'] = self.dmg_line_counter
                change = True
                self.total_damage_received += damage

                if self.configuration.get(
                        'AnnounceAllyDamage') == 'True' and current_vehicle_id != attacker_id and damage > 0 and \
                                damage >= self.configuration.get('MinimumAllyDamage'):
                    text = self.configuration.get('AllyDamageMessage')
                    text, ammo = self.check_macros(text, battle_id, -1, attack_reason_id, attacker_id, damage,
                                                   effects_index, place)
                    player.broadcast(chatManager.battleTeamChannelID, text.encode('utf8', 'xmlcharrefreplace'))

                if self.configuration.get(
                        'AnnounceAllyDamageOnlyMe') == 'True' and current_vehicle_id != attacker_id and damage > 0:
                    text = self.configuration.get('AllyDamageMessageForYou')
                    text, ammo = self.check_macros(text, battle_id, -1, attack_reason_id, attacker_id, damage,
                                                   effects_index, place)
                    MessengerEntry.g_instance.gui.addClientMessage(text)

        if self.is_it_last == 1:
            self.is_it_last = 2

        if change:
            for z in xrange(0, len(self.window_key_list)):
                damagelog_position = self.dmg_line_counter
                for z1 in xrange(0, len(self.config_key[z])):
                    line_nr = self.check_line(self.config_key[z][z1]['LineType'])
                    if line_nr == 6:
                        for z2 in xrange(0, len(self.line_types_original[line_nr])):
                            unid_txt = '1' + str(z) + str(z1) + str(z2)
                            unid = int(unid_txt)
                            if damagelog_position < 1:
                                self.window_labels_key[unid].text = ''
                            else:
                                damagelog_switch = self.line_types_original[line_nr][z2]['width']
                                text = str(self.line_types_original[line_nr][z2]['text'])
                                curr_battle_id = self.damagelog_list[damagelog_position]['battleID']
                                curr_attack_reason_id = self.damagelog_list[damagelog_position]['attackReasonID']
                                curr_attacker_id = self.damagelog_list[damagelog_position]['attackerID']
                                curr_damage = self.damagelog_list[damagelog_position]['Damage']
                                curr_effects_index = self.damagelog_list[damagelog_position]['effectsIndex']
                                curr_place = self.damagelog_list[damagelog_position]['place']
                                curr_type = self.damagelog_list[damagelog_position]['type']
                                damage_nr = self.damagelog_list[damagelog_position]['Nr']
                                self.window_labels_key[unid].text, ammo = self.check_macros(text, curr_battle_id, -1,
                                                                                            curr_attack_reason_id,
                                                                                            curr_attacker_id,
                                                                                            curr_damage,
                                                                                            curr_effects_index,
                                                                                            curr_place,
                                                                                            damagelog_switch, damage_nr)
                                self.window_labels_key[unid].colour = self.check_color(
                                    self.line_types_original[line_nr][z2]['color'], curr_type, ammo,
                                    curr_attack_reason_id)
                        damagelog_position -= 1
        self.update_efficiencies()

    # todo evaluate necessity of battle_id argument?
    def update_hp_left(self, battle_id):
        counter = 1
        self.enemy_tank_list_sorted.clear()
        for z in xrange(1, self.tank_counter_enemy):
            try:
                self.tank_list_enemy[z]['currentHealth'] = BigWorld.entity(self.tank_list_enemy[z]['battleID']).health
            finally:
                pass
            if self.tank_list_enemy[z]['currentHealth'] > 0:
                self.enemy_tank_list_sorted[counter]['currentHealth'] = self.tank_list_enemy[z]['currentHealth']
                self.enemy_tank_list_sorted[counter]['tankName'] = self.tank_list_enemy[z]['tankName']
                self.enemy_tank_list_sorted[counter]['playerName'] = self.tank_list_enemy[z]['playerName']
                self.enemy_tank_list_sorted[counter]['team'] = self.tank_list_enemy[z]['team']
                self.enemy_tank_list_sorted[counter]['maxHealth'] = self.tank_list_enemy[z]['maxHealth']
                self.enemy_tank_list_sorted[counter]['battleID'] = self.tank_list_enemy[z]['battleID']
                counter += 1
        for z in xrange(0, len(self.window_key_list)):
            hp_left_pos = 1
            for z1 in xrange(0, len(self.config_key[z])):
                line_nr = self.check_line(self.config_key[z][z1]['LineType'])
                if line_nr == 7:
                    hp_left_pos += 1
                    if hp_left_pos == self.tank_counter_enemy:
                        hp_left_pos = self.tank_counter_enemy
                    for z2 in xrange(0, len(self.line_types_original[line_nr])):
                        unid_txt = '1' + str(z) + str(z1) + str(z2)
                        unid = int(unid_txt)
                        hp_left_width = self.line_types_original[line_nr][z2]['width']
                        text = str(self.line_types_original[line_nr][z2]['text'])
                        self.window_labels_key[unid].text, ammo = self.check_macros(text, 0, hp_left_pos, 0, 0, 0, 0, 0,
                                                                                    hp_left_width)
                        self.window_labels_key[unid].colour = self.check_color(
                            self.line_types_original[line_nr][z2]['color'],
                            '', ammo, 0)
        self.update_efficiencies()

    # noinspection PyProtectedMember
    def update_info_panel(self):

        player = None
        target = None

        time_past = int(self.my_ip_timer - time.time())
        sec_to_reset = self.configuration.get('timeToShowOwnInfo')
        if not BigWorld.target() and time_past < sec_to_reset:
            # todo Why surround with try: except:, does this ever fail?
            try:
                player = BigWorld.player()
                target = player.getVehicleAttached()
            finally:
                pass

        if player is None or target is None:
            # todo stop executing?
            logger.warn('MultiHitLog - update_info_panel :- BigWorld.player() / getVehicleAttached() returned None')

        if BigWorld.target():
            self.my_ip_timer = time.time()
            self.infopanel_switch = True
            player = BigWorld.player()
            target = BigWorld.target()

        try:
            type_descr = target.typeDescriptor
            vehicle_type_descr = player.vehicleTypeDescriptor
            self.targeted_tank_descr['TankName'] = type_descr.type.userString
            self.targeted_tank_descr['hullArmor'] = [int(type_descr.hull['primaryArmor'][0]),
                                                     int(type_descr.hull['primaryArmor'][1]),
                                                     int(type_descr.hull['primaryArmor'][2])]
            self.targeted_tank_descr['turretArmor'] = [int(type_descr.turret['primaryArmor'][0]),
                                                       int(type_descr.turret['primaryArmor'][1]),
                                                       int(type_descr.turret['primaryArmor'][2])]
            self.targeted_tank_descr['gunName'] = type_descr.gun['shortUserString']
            # todo Add AssumeVentilation and AssumeRammer to configuration files and implement
            loader_skill = 132
            other_bonus = 0.9
            self.targeted_tank_descr['ReloadTime'] = type_descr.gun['reloadTime'] * 0.875 / (
                0.00375 * loader_skill + 0.5) * other_bonus
            self.targeted_tank_descr['ViewRange'] = int(type_descr.turret['circularVisionRadius'])
            self.targeted_tank_descr['pWeight'] = \
                int(round(vehicle_type_descr._VehicleDescr__computeWeight()[0] / 1000))
            self.targeted_tank_descr['vWeight'] = int(round(type_descr._VehicleDescr__computeWeight()[0] / 1000))

            z = 0
            for element in type_descr.gun['shots']:
                self.targeted_tank_descr['shellDamage'][z] = int(element['shell']['damage'][0])
                z += 1

            z = 0
            for element in type_descr.gun['shots']:
                self.targeted_tank_descr['shellPower'][z] = int(element['piercingPower'][0])
                z += 1

            z = 0
            for element in type_descr.gun['shots']:
                if element['shell']['kind'] == 'ARMOR_PIERCING':
                    self.targeted_tank_descr['shellType'][z] = element['shell']['kind'].replace('ARMOR_PIERCING', 'AP')
                elif element['shell']['kind'] == 'HIGH_EXPLOSIVE':
                    self.targeted_tank_descr['shellType'][z] = element['shell']['kind'].replace('HIGH_EXPLOSIVE', 'HE')
                elif element['shell']['kind'] == 'ARMOR_PIERCING_CR':
                    self.targeted_tank_descr['shellType'][z] = element['shell']['kind'].replace('ARMOR_PIERCING_CR',
                                                                                                'CR')
                else:
                    self.targeted_tank_descr['shellType'][z] = element['shell']['kind'].replace('HOLLOW_CHARGE', 'HC')
                z += 1
        except IndexError:
            # todo error logging
            pass
        except KeyError:
            # todo error logging
            pass
        except TypeError:
            # todo error logging
            pass
        except ValueError:
            # todo error logging
            pass
        finally:
            pass

        weight_diff = 'same'
        for z in xrange(0, len(self.window_key_list)):
            for z1 in xrange(0, len(self.config_key[z])):
                line_nr = self.check_line(self.config_key[z][z1]['LineType'])
                if line_nr != 4 and line_nr != 6 and line_nr != 7:
                    for z2 in xrange(0, len(self.line_types_original[line_nr])):
                        unid_txt = '1' + str(z) + str(z1) + str(z2)
                        unid = int(unid_txt)
                        width = self.line_types_original[line_nr][z2]['width']
                        if self.line_types_original[line_nr][z2]['color'] == 'weight':
                            p_weight = self.targeted_tank_descr.get('pWeight')
                            v_weight = self.targeted_tank_descr.get('vWeight')
                            weight_diff = 'same'
                            if int(p_weight or 0) < int(v_weight or 0):
                                weight_diff = 'more'
                            elif int(p_weight or 0) > int(v_weight or 0):
                                weight_diff = 'less'
                        self.window_labels_key[unid].text, ammo = self.check_macros(
                            self.line_types_original[line_nr][z2]['text'], 0, -1, 0, 0, 0, 0, 0, width)
                        self.window_labels_key[unid].colour = self.check_color(
                            self.line_types_original[line_nr][z2]['color'],
                            '', ammo, 0, weight_diff)

    def check_line(self, line_type):
        return int(line_type[4:])

# noinspection PyProtectedMember
old_PlayerAvatar_setVisibleGUI = PlayerAvatar._PlayerAvatar__setVisibleGUI


# noinspection PyPep8Naming
def new_PlayerAvatar_setVisibleGUI(self, visible):
    old_PlayerAvatar_setVisibleGUI(self, visible)
    HitLog.set_visible(visible)


PlayerAvatar._PlayerAvatar__setVisibleGUI = new_PlayerAvatar_setVisibleGUI
old_Battle_afterCreate = Battle.afterCreate


# noinspection PyPep8Naming
def new_Battle_afterCreate(self):
    old_Battle_afterCreate(self)
    HitLog.create_windows()
    HitLog.create_labels()
    key_monitor()
    HitLog.update_efficiencies()


Battle.afterCreate = new_Battle_afterCreate
old_Battle_beforeDelete = Battle.beforeDelete


# noinspection PyPep8Naming
def new_beforeDelete(self):
    old_Battle_beforeDelete(self)
    HitLog.reset_data()
    HitLog.delete_window()


Battle.beforeDelete = new_beforeDelete
old_Vehicle_onEnterWorld = Vehicle.onEnterWorld


# noinspection PyPep8Naming
def new_Vehicle_onEnterWorld(self, prereqs):
    old_Vehicle_onEnterWorld(self, prereqs)
    player = BigWorld.player()
    __vID = BigWorld.player().playerVehicleID
    # todo do we need vehicle?
    # vehicle = BigWorld.entity(__vID)
    typeDescriptor = vehicles.VehicleDescr(compactDescr=self.publicInfo.compDescr)
    for key, vehicle in player.arena.vehicles.iteritems():
        if vehicle['name'] == self.publicInfo.name:
            HitLog.myBattleID = key
            HitLog.tank_list_descr[key]['currentHealth'] = BigWorld.entity(key).health
            exist = False
            if player.team == BigWorld.player().arena.vehicles.get(key)['team']:
                z = HitLog.tank_counter_ally
                for y in xrange(0, z):
                    if HitLog.tank_list_ally[y]:
                        if HitLog.tank_list_ally[y]['battleID'] == key:
                            exist = True
                            HitLog.tank_list_ally[y]['currentHealth'] = BigWorld.entity(key).health
                if not exist:
                    HitLog.tank_list_ally[z]['tankName'] = typeDescriptor.type.shortUserString
                    HitLog.tank_list_ally[z]['playerName'] = BigWorld.player().arena.vehicles.get(key)['name']
                    HitLog.tank_list_ally[z]['team'] = BigWorld.player().arena.vehicles.get(key)['team']
                    HitLog.tank_list_ally[z]['maxHealth'] = typeDescriptor.maxHealth
                    HitLog.tank_list_ally[z]['currentHealth'] = BigWorld.entity(key).health
                    HitLog.tank_list_ally[z]['battleID'] = key
                    HitLog.tank_counter_ally += 1
            if player.team != BigWorld.player().arena.vehicles.get(key)['team']:
                z = HitLog.tank_counter_enemy
                for y in xrange(0, z):
                    if HitLog.tank_list_enemy[y]:
                        if HitLog.tank_list_enemy[y]['battleID'] == key:
                            exist = True
                            HitLog.tank_list_enemy[y]['currentHealth'] = BigWorld.entity(key).health
                if not exist:
                    HitLog.tank_list_enemy[z]['tankName'] = typeDescriptor.type.shortUserString
                    HitLog.tank_list_enemy[z]['playerName'] = BigWorld.player().arena.vehicles.get(key)['name']
                    HitLog.tank_list_enemy[z]['team'] = BigWorld.player().arena.vehicles.get(key)['team']
                    HitLog.tank_list_enemy[z]['maxHealth'] = typeDescriptor.maxHealth
                    HitLog.tank_list_enemy[z]['currentHealth'] = BigWorld.entity(key).health
                    HitLog.tank_list_enemy[z]['battleID'] = key
                    HitLog.tank_counter_enemy += 1
            HitLog.update_hp_left(key)
            if key == __vID:
                HitLog.pass_type_descriptor(typeDescriptor)
            break


Vehicle.onEnterWorld = new_Vehicle_onEnterWorld
old_Vehicle_showDamageFromShot = Vehicle.showDamageFromShot


# noinspection PyPep8Naming
def new_Vehicle_showDamageFromShot(self, attackerID, points, effectsIndex):
    old_Vehicle_showDamageFromShot(self, attackerID, points, effectsIndex)

    player = BigWorld.player()
    place = ''
    for battleID, vehicle in player.arena.vehicles.iteritems():
        if vehicle['name'] == self.publicInfo.name:
            # todo evaluate necessity of unused variables
            # effectsDescr = vehicles.g_cache.shotEffects[effectsIndex]
            maxHitEffectCode, decodedPoints = DamageFromShotDecoder.decodeHitPoints(points, HitLog.type_descriptor)
            # hasPiercedHit = DamageFromShotDecoder.hasDamaged(maxHitEffectCode)
            HitLog.hit_type = effectsIndex
            #print str(effectsDescr)
            #print str(HIT_EFFECT[maxHitEffectCode])
            #print str(decodedPoints[0][0])
            #print str(decodedPoints[0][2])
            #print str(hasPiercedHit)
            #print str(effectsIndex)
            if battleID == BigWorld.player().playerVehicleID:
                if decodedPoints[0][2]:
                    if decodedPoints[0][2] == 'armorCriticalHit':
                        place = str(decodedPoints[0][0])
                HitLog.update_damage_log(battleID, attackerID, 0, 0, effectsIndex, 9999, time.time(), place)
            HitLog.update_hp_left(battleID)
            break


Vehicle.showDamageFromShot = new_Vehicle_showDamageFromShot
old_Vehicle_onHealthChanged = Vehicle.onHealthChanged


# noinspection PyPep8Naming
def new_Vehicle_onHealthChanged(self, newHealth, attackerID, attackReasonID):
    old_Vehicle_onHealthChanged(self, newHealth, attackerID, attackReasonID)
    myDamage = 0
    myHealth = 9999
    player = BigWorld.player()
    for battleID, vehicle in player.arena.vehicles.iteritems():
        if vehicle['name'] == self.publicInfo.name:
            if battleID == BigWorld.player().playerVehicleID:
                myHealth = HitLog.tank_list_descr[battleID]['currentHealth']
                if newHealth <= 0 and HitLog.is_it_last == 0:
                    HitLog.is_it_last = 1
            if 'currentHealth' in HitLog.tank_list_descr[battleID]:
                myDamage = HitLog.tank_list_descr[battleID]['currentHealth'] - newHealth
                HitLog.tank_list_descr[battleID]['currentHealth'] = newHealth
                if BigWorld.player().playerVehicleID == attackerID:
                    HitLog.update_total_damage(battleID, myDamage, newHealth, attackerID, attackReasonID)
            HitLog.update_damage_log(battleID, attackerID, attackReasonID, myDamage, HitLog.hit_type, myHealth,
                                     time.time(), '')
            HitLog.update_hp_left(battleID)


Vehicle.onHealthChanged = new_Vehicle_onHealthChanged


def key_monitor():
    # todo add key filtering
    if BigWorld.isKeyDown(Keys.KEY_SPACE):
        HitLog.key_pressed('KEY_SPACE')
    elif BigWorld.isKeyDown(Keys.KEY_LSHIFT):
        HitLog.key_pressed('KEY_LSHIFT')
    elif BigWorld.isKeyDown(Keys.KEY_LALT):
        HitLog.key_pressed('KEY_LALT')
    elif BigWorld.isKeyDown(Keys.KEY_CAPSLOCK):
        HitLog.key_pressed('KEY_CAPSLOCK')
    elif BigWorld.isKeyDown(Keys.KEY_LCONTROL):
        HitLog.key_pressed('KEY_LCONTROL')
    elif BigWorld.isKeyDown(Keys.KEY_B):
        HitLog.key_pressed('KEY_B')
    elif BigWorld.isKeyDown(Keys.KEY_C):
        HitLog.key_pressed('KEY_C')
    elif BigWorld.isKeyDown(Keys.KEY_E):
        HitLog.key_pressed('KEY_E')
    elif BigWorld.isKeyDown(Keys.KEY_F):
        HitLog.key_pressed('KEY_F')
    elif BigWorld.isKeyDown(Keys.KEY_G):
        HitLog.key_pressed('KEY_G')
    elif BigWorld.isKeyDown(Keys.KEY_H):
        HitLog.key_pressed('KEY_H')
    elif BigWorld.isKeyDown(Keys.KEY_I):
        HitLog.key_pressed('KEY_I')
    elif BigWorld.isKeyDown(Keys.KEY_J):
        HitLog.key_pressed('KEY_J')
    elif BigWorld.isKeyDown(Keys.KEY_K):
        HitLog.key_pressed('KEY_K')
    elif BigWorld.isKeyDown(Keys.KEY_L):
        HitLog.key_pressed('KEY_L')
    elif BigWorld.isKeyDown(Keys.KEY_M):
        HitLog.key_pressed('KEY_M')
    elif BigWorld.isKeyDown(Keys.KEY_N):
        HitLog.key_pressed('KEY_N')
    elif BigWorld.isKeyDown(Keys.KEY_O):
        HitLog.key_pressed('KEY_O')
    elif BigWorld.isKeyDown(Keys.KEY_P):
        HitLog.key_pressed('KEY_P')
    elif BigWorld.isKeyDown(Keys.KEY_Q):
        HitLog.key_pressed('KEY_Q')
    elif BigWorld.isKeyDown(Keys.KEY_R):
        HitLog.key_pressed('KEY_R')
    elif BigWorld.isKeyDown(Keys.KEY_T):
        HitLog.key_pressed('KEY_T')
    elif BigWorld.isKeyDown(Keys.KEY_U):
        HitLog.key_pressed('KEY_U')
    elif BigWorld.isKeyDown(Keys.KEY_V):
        HitLog.key_pressed('KEY_V')
    elif BigWorld.isKeyDown(Keys.KEY_X):
        HitLog.key_pressed('KEY_X')
    elif BigWorld.isKeyDown(Keys.KEY_Y):
        HitLog.key_pressed('KEY_Y')
    elif BigWorld.isKeyDown(Keys.KEY_Z):
        HitLog.key_pressed('KEY_Z')
    elif BigWorld.isKeyDown(Keys.KEY_1):
        HitLog.key_pressed('KEY_1')
    elif BigWorld.isKeyDown(Keys.KEY_2):
        HitLog.key_pressed('KEY_2')
    elif BigWorld.isKeyDown(Keys.KEY_3):
        HitLog.key_pressed('KEY_3')
    elif BigWorld.isKeyDown(Keys.KEY_4):
        HitLog.key_pressed('KEY_4')
    elif BigWorld.isKeyDown(Keys.KEY_5):
        HitLog.key_pressed('KEY_5')
    elif BigWorld.isKeyDown(Keys.KEY_6):
        HitLog.key_pressed('KEY_6')
    elif BigWorld.isKeyDown(Keys.KEY_7):
        HitLog.key_pressed('KEY_7')
    elif BigWorld.isKeyDown(Keys.KEY_8):
        HitLog.key_pressed('KEY_8')
    elif BigWorld.isKeyDown(Keys.KEY_9):
        HitLog.key_pressed('KEY_9')
    elif BigWorld.isKeyDown(Keys.KEY_0):
        HitLog.key_pressed('KEY_0')
    elif BigWorld.isKeyDown(Keys.KEY_NUMPAD1):
        HitLog.key_pressed('KEY_NUMPAD1')
    elif BigWorld.isKeyDown(Keys.KEY_NUMPAD2):
        HitLog.key_pressed('KEY_NUMPAD2')
    elif BigWorld.isKeyDown(Keys.KEY_NUMPAD3):
        HitLog.key_pressed('KEY_NUMPAD3')
    elif BigWorld.isKeyDown(Keys.KEY_NUMPAD4):
        HitLog.key_pressed('KEY_NUMPAD4')
    elif BigWorld.isKeyDown(Keys.KEY_NUMPAD5):
        HitLog.key_pressed('KEY_NUMPAD5')
    elif BigWorld.isKeyDown(Keys.KEY_NUMPAD6):
        HitLog.key_pressed('KEY_NUMPAD6')
    elif BigWorld.isKeyDown(Keys.KEY_NUMPAD7):
        HitLog.key_pressed('KEY_NUMPAD7')
    elif BigWorld.isKeyDown(Keys.KEY_NUMPAD8):
        HitLog.key_pressed('KEY_NUMPAD8')
    elif BigWorld.isKeyDown(Keys.KEY_NUMPAD9):
        HitLog.key_pressed('KEY_NUMPAD9')
    elif BigWorld.isKeyDown(Keys.KEY_NUMPAD0):
        HitLog.key_pressed('KEY_NUMPAD0')
    elif BigWorld.isKeyDown(Keys.KEY_NUMLOCK):
        HitLog.key_pressed('KEY_NUMLOCK')
    elif BigWorld.isKeyDown(Keys.KEY_NUMPADCOMMA):
        HitLog.key_pressed('KEY_NUMPADCOMMA')
    elif BigWorld.isKeyDown(Keys.KEY_NUMPADENTER):
        HitLog.key_pressed('KEY_NUMPADENTER')
    elif BigWorld.isKeyDown(Keys.KEY_NUMPADEQUALS):
        HitLog.key_pressed('KEY_NUMPADEQUALS')
    elif BigWorld.isKeyDown(Keys.KEY_NUMPADMINUS):
        HitLog.key_pressed('KEY_NUMPADMINUS')
    elif BigWorld.isKeyDown(Keys.KEY_NUMPADPERIOD):
        HitLog.key_pressed('KEY_NUMPADPERIOD')
    elif BigWorld.isKeyDown(Keys.KEY_NUMPADSLASH):
        HitLog.key_pressed('KEY_NUMPADSLASH')
    elif BigWorld.isKeyDown(Keys.KEY_NUMPADSTAR):
        HitLog.key_pressed('KEY_NUMPADSTAR')
    else:
        HitLog.key_pressed('NONE')
        HitLog.update_info_panel()
    BigWorld.callback(0.1, key_monitor)
    return


HitLog = MultiHitLog()




